#include "changemanager.h"

CXChangeManager::CXChangeManager(void)
{
}

CXChangeManager::~CXChangeManager(void)
{
}

Error CXChangeManager::Register(pSubject subj, pObserver obs)
{
	if(subj == NULL || obs == NULL)
		return Error::Wrong_address;
	SubjectList::iterator i = _subjectList.begin();
	for(; i != _subjectList.end(); ++i)
		if(i->_psubject == subj) break;
	if(i != _subjectList.end())
	{
		try
		{
			i->_observerList.push_back(obs);
		}
		catch(...)
		{
			return Error::Out_of_memory;
		}
	}
	else
	{
		SubjectInfo info;
		info._psubject = subj;
		try
		{
			info._observerList.push_back(obs);
			_subjectList.push_back(info);
			obs->Update(subj);
		}
		catch(...)
		{
			return Error::Out_of_memory;
		}
	}
	return Error::Success;
}

Error CXChangeManager::Unregister(pSubject subj, pObserver obs)
{
	if(subj == NULL || obs == NULL)
		return Error::Wrong_address;
	SubjectList::iterator i = _subjectList.begin();
	for(; i != _subjectList.end(); ++i)
		if(i->_psubject == subj) break;
	if(i != _subjectList.end())
	{
		try
		{
			i->_observerList.remove(obs);
		}
		catch(...)
		{
			return Error::Wrong_address;
		}
		if(i->_observerList.size() == 0)
			_subjectList.erase(i);
	}
	else
		return Error::Wrong_address;
	return Error::Success;
}

Error CXChangeManager::Update(pSubject subj)
{
	if(subj == NULL)
		return Error::Wrong_address;
	SubjectList::iterator i = _subjectList.begin();
	for(; i != _subjectList.end(); ++i)
		if(i->_psubject == subj) break;
	if(i != _subjectList.end())
	{
		try
		{
			SubjectInfo* info = i;
			_updatedsubjects.push_back(info);
		}
		catch(...)
		{
			return Error::Wrong_address;
		}
		
	}
	else
		return Error::Wrong_address;

	return Error::Success;
}

void CXChangeManager::DistributeChanges()
{
	pObserver pObs = NULL;
	SubjectInfo* pSubjInfo = NULL;
	for(std::list<SubjectInfo*>::iterator i = _updatedsubjects.begin(); i != _updatedsubjects.end(); ++i)
	{
		pSubjInfo = *i;
		for(ObserverList::iterator j = pSubjInfo->_observerList.begin();
			j != pSubjInfo->_observerList.end(); ++j)
		{
			pObs = *j;
			pObs->Update(pSubjInfo->_psubject);
		}
	}
}